Skip to content

Fix message reactions overlay gesture handling#1424

Merged
nuno-vieira merged 12 commits intodevelopfrom
fix/message-reactions-overlay-gestures
Apr 21, 2026
Merged

Fix message reactions overlay gesture handling#1424
nuno-vieira merged 12 commits intodevelopfrom
fix/message-reactions-overlay-gestures

Conversation

@nuno-vieira
Copy link
Copy Markdown
Member

@nuno-vieira nuno-vieira commented Apr 17, 2026

https://linear.app/stream/issue/IOS-1641/v5-qa-message-reactions-overlay-gesture-fixes

🎯 Goal

Fix a set of gesture issues in the reactions overlay view that made the overlay behave unexpectedly when interacting with the previewed message:

  • Tapping a message with an image (or any media) opened the fullscreen gallery instead of staying in the overlay.
  • Tapping the empty space around the previewed message bubble did not dismiss the overlay.
  • Long messages in the overlay were not scrollable when using a heavier hit-testing workaround.
  • Long-pressing a message with attachments occasionally opened the fullscreen gallery, because the child attachment tap gesture raced with the parent long-press.

🛠 Implementation

  • MessageItemView: use .contentShape(Rectangle()) so the entire cell (including empty lateral space) participates in hit-testing, and switch the message long-press from .simultaneousGesture to .highPriorityGesture. The high-priority long-press wins against child tap gestures, so media attachments no longer fire their tap action when the user is long-pressing.
  • MessageContainerView: when shown as preview inside the overlay, attach a .highPriorityGesture(TapGesture()) that swallows taps on the bubble only. This keeps the bubble non-interactive inside the overlay while leaving scrolling and other gestures intact.
  • ReactionsOverlayView: add an .onTapGesture on the message item view wrapper that dismisses the overlay when the user taps the empty cell area around the preview bubble.

Net effect:

  • Tapping the bubble (or its attachments) inside the overlay does nothing.
  • Tapping empty space inside the overlay (around the bubble, between the reactions picker and message actions) dismisses the overlay.
  • Long messages remain scrollable inside the overlay.
  • Long-pressing over attachments never opens the gallery.

🎨 Showcase

N/A — behavioral fix, no UI changes.

🧪 Manual Testing Notes

  • Long-press a message with a single image attachment. Confirm the gallery does not open and the reactions overlay appears.
  • With the overlay open, tap the image inside the preview — nothing should happen.
  • Tap the empty space at the sides of the preview bubble — the overlay should dismiss.
  • Open the overlay on a message with a long text body and scroll the preview — scrolling should work.
  • Long-press several times on messages with media to confirm the gallery never opens on long-press.

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • CHANGELOG is updated

Summary by CodeRabbit

  • Bug Fixes

    • Prevented tapping media in the reactions overlay from opening the fullscreen gallery.
    • Tapping empty space around a previewed message now dismisses the reactions overlay.
    • Stopped long-pressing messages with attachments from intermittently opening the fullscreen gallery.
  • New Features

    • Improved media thumbnails for images and videos with better loading, retry behavior, and playback overlay handling.

@nuno-vieira nuno-vieira requested a review from a team as a code owner April 17, 2026 16:52
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Prevent taps/long-presses on previewed messages from opening the fullscreen gallery and add tap-to-dismiss regions for the reactions overlay; image/video thumbnail loading was refactored and test hooks for sync image lookup were introduced for snapshot tests.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Moved three items from "Upcoming" → "Fixed": prevented media-tap opening fullscreen gallery from overlay, enabled tapping empty space to dismiss overlay, and stopped long-press from intermittently opening gallery.
Gesture handling (message & container)
Sources/StreamChatSwiftUI/ChatMessageList/MessageItemView.swift, Sources/StreamChatSwiftUI/ChatMessageList/MessageContainerView.swift
Replaced previous hit-testing/gesture wiring with a MessageActionsGestureModifier that conditionally attaches double-tap and a high-priority long-press, and added a conditional .highPriorityGesture(TapGesture()) on previewed message bubbles to swallow taps and prevent attachment/fullscreen propagation.
Reactions overlay dismissal
Sources/StreamChatSwiftUI/ChatMessageList/Reactions/ReactionsOverlayView.swift
Added contentShape(Rectangle()) and onTapGesture handlers to the geometry background and main VStack so tapping empty surrounding space dismisses the reactions overlay.
Media thumbnail & playback UI
Sources/StreamChatSwiftUI/ChatMessageList/MessageMediaAttachmentContentView.swift
Refactored image/video thumbnail rendering: replaced manual state + loader with StreamAsyncImage for images, introduced video-specific preview state and thumbnail generation, unified overlay helpers, adjusted retry and playback overlay logic.
Image loader test hook
Sources/StreamChatSwiftUI/CommonViews/NukeImageLoader.swift
Added nonisolated test-only sync hook testSyncLookup to allow synchronous StreamAsyncImageResult lookup during tests, consulted before cache/memory lookup.
Tests & mocks adjustments
StreamChatSwiftUITests/Infrastructure/Mocks/MediaLoader_Mock.swift, .../StreamChatTestCase.swift, .../NukeImageLoader_Tests.swift
Made imageForURL internal and moved mock state updates onto main actor; StreamChatTestCase reuses a single MediaLoader_Mock, sets NukeImageLoader.testSyncLookup in setup and clears it in teardown for snapshot tests; NukeImageLoader_Tests disables the test hook in setUp.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Overlay as ReactionsOverlayView
    participant Message as MessageItemView / MessageContainerView
    participant Attachment as Attachment / FullscreenGallery
    participant ImageLoader as NukeImageLoader / StreamAsyncImage

    User->>Overlay: tap empty overlay area
    Note right of Overlay: contentShape + onTapGesture
    Overlay-->>User: dismiss overlay

    User->>Message: tap message bubble (shownAsPreview)
    Note right of Message: highPriority TapGesture swallows tap
    Message--x Attachment: tap does not propagate to gallery

    User->>Message: long-press on message with attachment
    Note right of Message: MessageActionsGestureModifier active only when not preview
    alt shownAsPreview == true
      Message--x Attachment: long-press ignored for gallery
    else
      Message->>Attachment: trigger actions / open gallery
    end

    Note over Message,ImageLoader: Image/video thumbnail loading via StreamAsyncImage / testSyncLookup hook
    ImageLoader->>Message: provide thumbnail phase (success/loading/error)
    Message-->>User: render thumbnail / overlays
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nudged the taps that wandered astray,
Hid sneaky presses from going astray.
Empty-space taps now politely depart,
Thumbnails load steady — no surprise jump-start.
Hooray, says the rabbit, gestures behave today.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'Fix message reactions overlay gesture handling' directly and accurately summarizes the main objective of the changeset, which is to fix gesture-related issues in the reactions overlay.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/message-reactions-overlay-gestures

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Replace the environment-based coordination with a single-modifier change: switching the message long-press from `simultaneousGesture` to `highPriorityGesture` cancels pending attachment tap recognizers when the long-press is recognized, preventing the gallery from opening on finger release.
@nuno-vieira nuno-vieira force-pushed the fix/message-reactions-overlay-gestures branch from 830e4fd to 8bef27f Compare April 17, 2026 16:57
@nuno-vieira nuno-vieira changed the base branch from main to develop April 17, 2026 16:58
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
Sources/StreamChatSwiftUI/ChatMessageList/Reactions/ReactionsOverlayView.swift (1)

86-91: Dismiss-on-empty-space fix looks correct.

Adding .contentShape(Rectangle()) + .onTapGesture to the Color.clear inside the GeometryReader is what actually makes the empty area dismiss the overlay — Color.clear already participates in hit-testing in SwiftUI, which is why taps there were previously being swallowed silently.

One small note: since this Color.clear fills the entire GeometryReader and sits above backgroundView in the outer ZStack, the pre-existing .onTapGesture on backgroundView (around line 196) is effectively shadowed for most of the screen. Not a functional issue, just potentially dead-ish code you could prune in a follow-up.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Sources/StreamChatSwiftUI/ChatMessageList/Reactions/ReactionsOverlayView.swift`
around lines 86 - 91, The empty-area-dismiss behavior was added by making the
Color.clear inside the GeometryReader participate in hit-testing via
.contentShape(Rectangle()) and attach an .onTapGesture that calls
dismissReactionsOverlay; keep this change but remove or consider pruning the
now-shadowed .onTapGesture on backgroundView (inside the outer ZStack) since the
Color.clear covers most of the screen and renders that handler dead code—update
or delete the backgroundView's tap handler to avoid redundancy and ensure
dismissReactionsOverlay remains the single tap-to-dismiss entrypoint.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@Sources/StreamChatSwiftUI/ChatMessageList/Reactions/ReactionsOverlayView.swift`:
- Around line 86-91: The empty-area-dismiss behavior was added by making the
Color.clear inside the GeometryReader participate in hit-testing via
.contentShape(Rectangle()) and attach an .onTapGesture that calls
dismissReactionsOverlay; keep this change but remove or consider pruning the
now-shadowed .onTapGesture on backgroundView (inside the outer ZStack) since the
Color.clear covers most of the screen and renders that handler dead code—update
or delete the backgroundView's tap handler to avoid redundancy and ensure
dismissReactionsOverlay remains the single tap-to-dismiss entrypoint.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a969694f-2a87-4b96-9749-c114ce25856f

📥 Commits

Reviewing files that changed from the base of the PR and between 70cef98 and 96b3fb2.

📒 Files selected for processing (21)
  • CHANGELOG.md
  • DemoAppSwiftUI/ChannelHeader/NewChatViewModel.swift
  • DemoAppSwiftUI/CreateGroupViewModel.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/Gallery/MediaViewer.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/GiphyAttachmentView.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/LinkAttachmentView.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MediaAttachment.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageContainerView.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageItemView.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/Reactions/ReactionsOverlayView.swift
  • Sources/StreamChatSwiftUI/CommonViews/StreamAsyncImage.swift
  • Sources/StreamChatSwiftUI/Utils.swift
  • Sources/StreamChatSwiftUI/Utils/StreamImageDownloader.swift
  • StreamChatSwiftUITests/Infrastructure/Mocks/MediaLoader_Mock.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/AttachmentCommandsPickerView_Tests.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerView_Tests.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageView_Tests.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/PollResultsView_Tests.swift
  • StreamChatSwiftUITests/Tests/StreamChatTestCase.swift
  • StreamChatSwiftUITests/Tests/Utils/MediaLoader_Tests.swift
  • StreamChatSwiftUITests/Tests/Utils/StreamChat_Utils_Tests.swift
💤 Files with no reviewable changes (16)
  • StreamChatSwiftUITests/Tests/ChatChannel/AttachmentCommandsPickerView_Tests.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/MediaAttachment.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/Gallery/MediaViewer.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/LinkAttachmentView.swift
  • StreamChatSwiftUITests/Tests/Utils/MediaLoader_Tests.swift
  • StreamChatSwiftUITests/Infrastructure/Mocks/MediaLoader_Mock.swift
  • DemoAppSwiftUI/ChannelHeader/NewChatViewModel.swift
  • Sources/StreamChatSwiftUI/CommonViews/StreamAsyncImage.swift
  • DemoAppSwiftUI/CreateGroupViewModel.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/PollResultsView_Tests.swift
  • Sources/StreamChatSwiftUI/ChatMessageList/GiphyAttachmentView.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageView_Tests.swift
  • Sources/StreamChatSwiftUI/Utils.swift
  • StreamChatSwiftUITests/Tests/StreamChatTestCase.swift
  • StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerView_Tests.swift
  • StreamChatSwiftUITests/Tests/Utils/StreamChat_Utils_Tests.swift

Copy link
Copy Markdown
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you tap in the message row to dismiss the overlay, there's a little delay, compared to when you tap on the area above or below to dismiss it.

@nuno-vieira nuno-vieira force-pushed the fix/message-reactions-overlay-gestures branch from 922be7e to 8bef27f Compare April 21, 2026 00:04
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Around line 12-15: Under the "Upcoming" section consolidate the two separate
"### 🐞 Fixed" subsections into a single "### 🐞 Fixed" subsection: move all
bullet entries (e.g., the three fix bullets shown) under one "### 🐞 Fixed"
heading and remove the duplicate heading so the changelog follows the Keep a
Changelog format (Added, Fixed, Changed) with a single Fixed subsection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 000fa1c2-d7d7-4860-b656-51a50695e140

📥 Commits

Reviewing files that changed from the base of the PR and between 4dff7ef and 41f82c8.

📒 Files selected for processing (1)
  • CHANGELOG.md

Comment thread CHANGELOG.md Outdated
@nuno-vieira
Copy link
Copy Markdown
Member Author

When you tap in the message row to dismiss the overlay, there's a little delay, compared to when you tap on the area above or below to dismiss it.

Fixed ✅

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
Sources/StreamChatSwiftUI/ChatMessageList/MessageItemView.swift (1)

214-232: Minor: branching @ViewBuilder changes view identity based on shownAsPreview.

Because the two branches return structurally different view trees (one with gestures attached, one without), SwiftUI will treat them as different view identities if shownAsPreview ever toggled at runtime, discarding gesture/animation state. It's initialized once and effectively constant for a given MessageItemView, so this is safe today — just noting it as a latent pitfall if shownAsPreview ever becomes reactive. An equivalent and slightly safer pattern would be to always attach the gestures with including: gated on shownAsPreview, similar to what MessageContainerView does for its tap swallow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageItemView.swift` around lines
214 - 232, The current `@ViewBuilder` body(content:) in MessageItemView returns
different view trees when shownAsPreview toggles (one branch without gestures
and one with gestures), which can change view identity; instead always attach
the gestures to the content and gate their actions on shownAsPreview so the view
structure remains constant. Concretely, keep the onTapGesture and
highPriorityGesture(LongPressGesture(minimumDuration: longPressMinimumDuration))
on the content unconditionally, but inside their closures first check
shownAsPreview (and isDoubleTapEnabled for the double-tap) and return early if
preview mode is active; still call onActionsTriggered() only when allowed. This
change should be made in the body(content:) function of MessageItemView
(affecting the onTapGesture, isDoubleTapEnabled, longPressMinimumDuration,
LongPressGesture and onActionsTriggered references).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Sources/StreamChatSwiftUI/ChatMessageList/MessageItemView.swift`:
- Around line 214-232: The current `@ViewBuilder` body(content:) in
MessageItemView returns different view trees when shownAsPreview toggles (one
branch without gestures and one with gestures), which can change view identity;
instead always attach the gestures to the content and gate their actions on
shownAsPreview so the view structure remains constant. Concretely, keep the
onTapGesture and highPriorityGesture(LongPressGesture(minimumDuration:
longPressMinimumDuration)) on the content unconditionally, but inside their
closures first check shownAsPreview (and isDoubleTapEnabled for the double-tap)
and return early if preview mode is active; still call onActionsTriggered() only
when allowed. This change should be made in the body(content:) function of
MessageItemView (affecting the onTapGesture, isDoubleTapEnabled,
longPressMinimumDuration, LongPressGesture and onActionsTriggered references).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: acaab135-2a11-4999-a338-130cf9cb240c

📥 Commits

Reviewing files that changed from the base of the PR and between 41f82c8 and f4b98ed.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageItemView.swift

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
Sources/StreamChatSwiftUI/CommonViews/NukeImageLoader.swift (1)

27-55: Test hook implementation looks good.

The early-return in cachedResult and the nonisolated(unsafe) storage are appropriate for a test-only synchronous resolver that defaults to nil in production. One small organizational nit: the // MARK: - Test Hook section is interleaved between cachedResult and storeCachingKey, which slightly fragments the public cache-lookup API. Moving the hook declaration to the end of the type (near the // MARK: - Private section) would keep the public lookup/store pair together. Non-blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/StreamChatSwiftUI/CommonViews/NukeImageLoader.swift` around lines 27
- 55, Move the test-only hook declaration nonisolated(unsafe) static var
testSyncLookup out of the middle of the public cache API so cachedResult and
storeCachingKey remain adjacent; specifically, remove the // MARK: - Test Hook
block from between cachedResult(...) and storeCachingKey(...) and reinsert the
testSyncLookup declaration at the end of the type near the // MARK: - Private
section to keep the public lookup/store pair together.
Sources/StreamChatSwiftUI/ChatMessageList/MessageMediaAttachmentContentView.swift (1)

118-128: Use .task(id:) for video thumbnail loading instead of onAppear guard.

The current onAppear { guard videoPreview == nil else { return } … } pattern has two issues:

  1. Stale thumbnail on source change: If the view position is reused with a different source.url (which can happen when the items array is reshaped), videoPreview retains the old attachment's cached image and loading is skipped.

  2. Retry re-triggering: After a failed load, videoPreviewError is set but videoPreview remains nil. Each re-appearance fires onAppear again, re-invoking loadVideoThumbnail() and potentially racing with a user-initiated retry tap.

Switching to .task(id: source.url) ties the load to the URL, re-runs on URL changes, and auto-cancels on view disappear. To support manual retry, add a videoRetryToken and include it in the task id, then have the retry overlay bump the token instead of calling loadVideoThumbnail() directly—mirroring the imageRetryToken pattern already in use.

♻️ Sketch
+    `@State` private var videoRetryToken = 0
+
     `@ViewBuilder`
     private var videoThumbnail: some View {
         ZStack {
             videoBackground
             videoOverlays
         }
-        .onAppear {
-            guard videoPreview == nil else { return }
-            loadVideoThumbnail()
-        }
+        .task(id: VideoLoadID(url: source.url, retry: videoRetryToken)) {
+            videoPreview = nil
+            loadVideoThumbnail()
+        }
     }

…and have the retry button in videoOverlays bump videoRetryToken &+= 1 instead of calling loadVideoThumbnail() directly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Sources/StreamChatSwiftUI/ChatMessageList/MessageMediaAttachmentContentView.swift`
around lines 118 - 128, Replace the onAppear guard-based loading in the
videoThumbnail View with a .task(id: ...) driven task that depends on the
attachment's source.url and a videoRetryToken so thumbnail loading re-runs when
the URL changes or a manual retry is triggered; specifically, remove the
onAppear { guard videoPreview == nil ... loadVideoThumbnail() } pattern in
videoThumbnail and instead invoke loadVideoThumbnail() inside .task(id:
(source.url, videoRetryToken)), add a videoRetryToken Int state (mirroring
imageRetryToken) and change the retry button in videoOverlays to bump
videoRetryToken (e.g., += 1) rather than calling loadVideoThumbnail() directly,
leaving existing videoPreview and videoPreviewError handling intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@Sources/StreamChatSwiftUI/ChatMessageList/MessageMediaAttachmentContentView.swift`:
- Around line 118-128: Replace the onAppear guard-based loading in the
videoThumbnail View with a .task(id: ...) driven task that depends on the
attachment's source.url and a videoRetryToken so thumbnail loading re-runs when
the URL changes or a manual retry is triggered; specifically, remove the
onAppear { guard videoPreview == nil ... loadVideoThumbnail() } pattern in
videoThumbnail and instead invoke loadVideoThumbnail() inside .task(id:
(source.url, videoRetryToken)), add a videoRetryToken Int state (mirroring
imageRetryToken) and change the retry button in videoOverlays to bump
videoRetryToken (e.g., += 1) rather than calling loadVideoThumbnail() directly,
leaving existing videoPreview and videoPreviewError handling intact.

In `@Sources/StreamChatSwiftUI/CommonViews/NukeImageLoader.swift`:
- Around line 27-55: Move the test-only hook declaration nonisolated(unsafe)
static var testSyncLookup out of the middle of the public cache API so
cachedResult and storeCachingKey remain adjacent; specifically, remove the //
MARK: - Test Hook block from between cachedResult(...) and storeCachingKey(...)
and reinsert the testSyncLookup declaration at the end of the type near the //
MARK: - Private section to keep the public lookup/store pair together.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9dcccd1-3cf4-40ab-ac2a-d1785e720945

📥 Commits

Reviewing files that changed from the base of the PR and between f4b98ed and 8be2620.

⛔ Files ignored due to path filters (7)
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_linkAttachmentView_customColors_snapshot.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_linkAttachmentView_snapshot.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewGiphy_snapshot.1.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewPendingGiphy_snapshot.default-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewPendingGiphy_snapshot.extraExtraExtraLarge-light.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewPendingGiphy_snapshot.rightToLeftLayout-default.png is excluded by !**/*.png
  • StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewPendingGiphy_snapshot.small-dark.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • Sources/StreamChatSwiftUI/ChatMessageList/MessageMediaAttachmentContentView.swift
  • Sources/StreamChatSwiftUI/CommonViews/NukeImageLoader.swift
  • StreamChatSwiftUITests/Infrastructure/Mocks/MediaLoader_Mock.swift
  • StreamChatSwiftUITests/Tests/CommonViews/NukeImageLoader_Tests.swift
  • StreamChatSwiftUITests/Tests/StreamChatTestCase.swift

@github-actions
Copy link
Copy Markdown

Public Interface

🚀 No changes affecting the public interface.

@Stream-SDK-Bot
Copy link
Copy Markdown
Collaborator

SDK Size

title develop branch diff status
StreamChatSwiftUI 8.04 MB 8.07 MB +27 KB 🟢

Copy link
Copy Markdown
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great now ✅

@Stream-SDK-Bot
Copy link
Copy Markdown
Collaborator

StreamChatSwiftUI XCSize

Object Diff (bytes)
MessageMediaAttachmentContentView.o +9541
ReactionsOverlayView.o +2434
MessageItemView.o +1531
MessageContainerView.o +1466

@sonarqubecloud
Copy link
Copy Markdown

@nuno-vieira nuno-vieira merged commit d854020 into develop Apr 21, 2026
11 of 12 checks passed
@nuno-vieira nuno-vieira deleted the fix/message-reactions-overlay-gestures branch April 21, 2026 14:13
@Stream-SDK-Bot Stream-SDK-Bot mentioned this pull request Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants